package org.jflame.auth;

import org.jflame.auth.authc.AuthcException;
import org.jflame.auth.authc.AuthcException.AuthcError;
import org.jflame.auth.authc.SimpleAuthcInfo;
import org.jflame.auth.authc.token.AuthToken;

/**
 * 身份认证服务抽象父类
 * 
 * @author yucan.zhang
 */
public abstract class BaseAuthService implements AuthService {

    @Override
    public SimpleAuthcInfo authenticate(AuthToken authToken) throws AuthcException {
        if (authToken == null) {
            throw new IllegalArgumentException("The authToken must not be null");
        }
        if (!supports(authToken)) {
            throw new AuthcException(this.getClass()
                    .getName() + " is not support auth token: "
                    + authToken.getClass()
                            .getSimpleName());
        }

        SimpleAuthcInfo authInfo = getAuthenticationInfo(authToken);
        if (authInfo == null) {
            throw new AuthcException(AuthcError.AccountNotFound);
        }
        if (authInfo.isLocked()) {
            throw new AuthcException(AuthcError.AccountLocked);
        }
        if (authInfo.isDisabled()) {
            throw new AuthcException(AuthcError.AccountDisabled);
        }
        if (authInfo.isCredentialExpired()) {
            throw new AuthcException(AuthcError.CredentialExpired);
        }
        if (doCredentialsMatch(authToken, authInfo)) {
            return authInfo;
        } else {
            throw new AuthcException(AuthcError.Credential);
        }
    }

    /**
     * 获取正确的身份信息
     * 
     * @param authToken
     * @return
     */
    protected abstract SimpleAuthcInfo getAuthenticationInfo(AuthToken authToken) throws AuthcException;

    /**
     * 判断密码凭证是否正确
     * 
     * @param authToken 输入的身份信息
     * @param authInfo 用户真正的身份信息
     * @return
     * @throws AuthcException
     */
    protected abstract boolean doCredentialsMatch(AuthToken authToken, SimpleAuthcInfo authInfo) throws AuthcException;

}
